package cn.jbolt.wechat.common.miniapp;


import cn.binarywang.wx.miniapp.bean.WxMaMessage;
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage;
import cn.hutool.core.util.StrUtil;
import cn.jbolt.core.base.config.JBoltConfig;
import cn.jbolt.wechat.common.mp.WechatMpContext;
import cn.jbolt.wechat.common.mp.WechatMpMessageHandler;
import cn.jbolt.wechat.model.WechatUser;
import cn.jbolt.wechat.service.JBoltWechatConfigService;
import cn.jbolt.wechat.service.JBoltWechatMenuEventProcesser;
import cn.jbolt.wechat.service.JBoltWechatReplyContentService;
import cn.jbolt.wechat.service.JBoltWechatUserService;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Inject;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 微信推送来的消息路由
 */
public class WechatMaMsgRouter {
    // 将 xml 和 in msg 存储到 request 中，解决控制器 单例的问题
    protected static final Log log = Log.getLog(WechatMaMsgRouter.class);
    public static final WechatMaMsgRouter me = new WechatMaMsgRouter();

    private  WxMaMessageRouter router = new WxMaMessageRouter(WechatMaContext.SERVICE);


    private WechatMaMsgRouter(){

        addTextHandler(router);
        addSessionHandler(router);
        addDefaultHandler(router);
    }


    /**
     * 文本消息处理
     * @param router
     */
    private void addTextHandler(WxMaMessageRouter router) {
        router.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).handler(new WechatMaMessageHandler(msg -> {
            WechatMaContext.sendText(msg.getFromUser(), "//接收到文本消息");
            return null;
        })).end();
    }
    /**
     * 文本消息处理
     * @param router
     */
    private void addSessionHandler(WxMaMessageRouter router) {
        router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event("user_enter_tempsession").handler(new WechatMaMessageHandler(msg -> {
            WechatMaContext.sendText(msg.getFromUser(), "//接收到临时会话");
            return null;
        })).end();
    }

    /**
     * 添加默认的路由映射
     * @param router
     */
    private void addDefaultHandler(WxMaMessageRouter router) {
        router.rule().async(false).handler(new WechatMaMessageHandler(msg -> {
            log.error("未能识别的小程序消息类型。 消息内容为：\n" + msg.toString());
            return null;
        })).end();
    }




    /**
     * 根据请求执行路由
     * @param request
     * @return
     */
    public  String route(HttpServletRequest request) {
        WxMaMessage fromMsg = getMessage(request);
        //解析消息的时候，做了特殊处理，如果消息是加密消息，会将encrypt的值设置为1
        boolean encrypt = Objects.equals(fromMsg.getEncrypt(), "1");
        WxMaXmlOutMessage outMsg = router.route(fromMsg);
        if (outMsg == null) {
            return "";
        }
        outMsg.setFromUserName(fromMsg.getToUser());
        outMsg.setToUserName(fromMsg.getFromUser());
        outMsg.setCreateTime(System.currentTimeMillis());
        if (encrypt) {
            return outMsg.toEncryptedXml(WechatMaContext.SERVICE.getWxMaConfig());
        }
        return outMsg.toXml();
    }

    /**
     * 从请求体中获取消息体
     * @param request
     * @return
     */
    private  WxMaMessage getMessage(HttpServletRequest request) {
        String inMsgXml = HttpKit.readData(request);
        if (StrKit.isBlank(inMsgXml)) {
            throw new RuntimeException("请不要在浏览器中请求该连接,调试请查看WIKI:http://git.oschina.net/jfinal/jfinal-weixin/wikis/JFinal-weixin-demo%E5%92%8C%E8%B0%83%E8%AF%95");
        }
        if (JBoltConfig.DEV_MODE) {
            System.out.println("接收消息:");
            System.out.println(inMsgXml);
        }
        String timestamp = getPara(request,"timestamp");
        String nonce = getPara(request,"nonce");
        String msg_signature = getPara(request,"msg_signature");
        String encrypt_type = getPara(request,"encrypt_type");
        if (msg_signature == null) {
            //明文模式
            return WxMaMessage.fromXml(inMsgXml);
        }
        WxMaMessage msg = WxMaMessage.fromEncryptedXml(inMsgXml, WechatMaContext.SERVICE.getWxMaConfig(), timestamp, nonce, msg_signature);
        //这里做了特殊处理，标记该条消息是加密过的
        msg.setEncrypt("1");
        return msg;
    }

    private  String getPara(HttpServletRequest request, String name) {
        String result = request.getParameter(name);
        return result != null && result.length() != 0 ? result : null;
    }
}
